package com.shenmazong.serverwebpoem.game;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.shenmazong.serverwebpoem.pojo.ObUserRaceScore;
import com.shenmazong.serverwebpoem.pojo.TbGameRoom;
import com.shenmazong.serverwebpoem.pojo.TbQuestion;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * @author 田不平
 * @project server-web-poem
 * @date 2020/4/10 9:19 AM
 * http://www.shenmazong.com
 */
@Data
@Slf4j
@Component
//@ServerEndpoint(value = "/choiceGame")
public class ChoiceQuestionWebSocket {

    private static Map<String, Session> onlineSessions = new ConcurrentHashMap<>();
    public static CopyOnWriteArraySet<ChoiceQuestionWebSocket> webSocketUsers = new CopyOnWriteArraySet<ChoiceQuestionWebSocket>();
    public static TbGameRoom waitRoom = null;
    public static TbGameRoom raceRoom = null;
    //
    private Session _session;
    private Integer userId = 0;                 // 用户ID
    private String nickName = "游客";            // 用户昵称
    private Integer roomId = 0;                 // 考场ID
    private Integer askId = 0;                  // 问题ID
    private Integer replyId = 0;                // 答案ID
    private Integer raceScore = 0;              // 比赛得分
    private Long sendTime = 0L;                 // 发题时间
    private String headUrl = "";                // 用户头像


    /**
     * TODO 客户端申请连接
     * @param session
     */
    @OnOpen
    public void onOpen(Session session) {
        this._session = session;
        onlineSessions.put(session.getId(), session);

        try {
            sendMessageAll("欢迎光临寒舍！！！");
        }catch (Exception e) {
            log.error("onOpen", e);
        }

        log.info("有新连接加入，当前在线数为" + onlineSessions.size());
    }

    /**
     * TODO 客户端关闭连接
     * @param session
     */
    @OnClose
    public void onClose(Session session) {

        onlineSessions.remove(session.getId());
        log.info("有一连接关闭！当前在线数为" + onlineSessions.size());
    }

    /**
     * TODO 收到客户端发来的消息
     * @param message
     * @param session
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        log.info("RECV:" + message);
        try{
            JSONObject ask = null;

            // 转换请求
            ask = JSON.parseObject(message);
            if(ask == null) {
                log.error("onMessage:"+message);
                return;
            }

            // 解析命令
            String cmd = ask.getString("cmd");
            if(cmd.equals(GameConst.GAME_RACE_CMD_JOIN)) {
                // 申请加入比赛
                doJoinRaceRoom(ask);
            }
            else if(cmd.equals(GameConst.GAME_RACE_CMD_REPLY)) {
                // 接收比赛答案
                doReplyQuestion(ask);
            }
            else {
                // 未知命令，不做处理
                log.error("未知命令:"+message);
            }
        }
        catch (Exception e) {
            log.info("onMessage:"+e);
        }
    }

    /**
     * TODO 客户端连接发生错误
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("LoginResultWebSocket 发生错误");
        error.printStackTrace();
    }

    /**
     * TODO 服务器客户端发送消息
     * @param session
     * @param message
     * @throws IOException
     */
    public void sendMessage(Session session, String message) throws IOException {
        session.getBasicRemote().sendText(message);
    }

    /**
     * TODO 服务器给所有客户端发送消息
     * @param message
     */
    public void sendMessageAll(String message) {
        for(String key : onlineSessions.keySet()){
            Session session = onlineSessions.get(key);

            try {
                sendMessage(session, message);
            }
            catch (Exception e) {
                log.error("sendMessageAll", e);
            }
        }
    }


    void doJoinRaceRoom(JSONObject ask) {
        // 获得用户信息
        if(ask.containsKey("userid"))
            setUserId(ask.getInteger("userid"));

        // 获取比赛房间信息

    }

    void doReplyQuestion(JSONObject ask) {

    }

    /**
     * TODO 计算房间人数
     * @param _roomId
     * @return
     */
    public static Integer getUserCountByRoomId(Integer _roomId) {
        Integer count = 0;

        for(ChoiceQuestionWebSocket user : webSocketUsers) {
            if(user.getRoomId() == _roomId)
                count ++;
        }

        return count;
    }

    /**
     * TODO 发送比赛准备命令
     * @param _roomId
     * @param _ltime
     */
    public static void sendRaceReadyByRoomId(Integer _roomId, Long _ltime) {
        Map<String, Object> map = new HashMap<String, Object>();

        map.put("cmd", GameConst.GAME_RACE_CMD_TIME);
        map.put("code", 0);
        map.put("seconds", _ltime);

        String reply = JSON.toJSONString(map);

        for(ChoiceQuestionWebSocket user : webSocketUsers) {
            if(user.getRoomId() == _roomId) {
                try {
                    user.sendMessage(user._session, reply);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * TODO 发送比赛开始命令
     */
    public static void sendRaceStartByRoomId(Integer _roomId, Integer askcount) {
        Map<String, Object> map = new HashMap<String, Object>();

        map.put("cmd", GameConst.GAME_RACE_CMD_START);
        map.put("code", 0);
        map.put("askcount", askcount);

        String reply = JSON.toJSONString(map);

        for(ChoiceQuestionWebSocket user : webSocketUsers) {
            if(user.getRoomId() == _roomId) {
                try {
                    user.sendMessage(user._session, reply);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * TODO 发送问题
     * @param _roomId
     * @param question
     */
    public static void sendRaceQuestionByRoomId(Integer _roomId, TbQuestion question) {
        Map<String, Object> map = new HashMap<String, Object>();

        map.put("cmd", GameConst.GAME_RACE_CMD_ASK);
        map.put("code", 0);
        map.put("waittime", 20);
        map.put("askno", 0);
        map.put("askid", question.getId());
        map.put("asktitle", question.getQuestion());
        map.put("reply1", question.getReply1());
        map.put("reply2", question.getReply2());
        map.put("reply3", question.getReply3());
        map.put("reply4", question.getReply4());

        String reply = JSON.toJSONString(map);

        for(ChoiceQuestionWebSocket user : webSocketUsers) {
            if(user.getRoomId() == _roomId) {
                try {
                    user.sendMessage(user._session, reply);

                    user.setAskId(question.getId());
                    user.setReplyId(question.getAnswer());
                    user.setSendTime(System.currentTimeMillis());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * TODO 发送排名
     * @param _roomId
     * @return
     */
    public static void sendRaceUserScoreTop(Integer _roomId) {

        ArrayList<ObUserRaceScore> scores = new ArrayList<>();

        // 计算排名
        for(ChoiceQuestionWebSocket user : webSocketUsers) {
            if(user.getRoomId() != _roomId)
                continue;

            ObUserRaceScore score = new ObUserRaceScore();
            score.setUserid(user.getUserId());
            score.setScore(user.getRaceScore());
            score.setNickname(user.getNickName());

            scores.add(score);
        }
        Collections.sort(scores);

        // 设置排名
        for(Integer idx=0; idx<scores.size(); idx++) {
            scores.get(idx).setTopno(idx+1);
        }

        //
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("cmd", GameConst.GAME_RACE_CMD_TOP);
        map.put("code", 0);
        map.put("position", 0);
        map.put("score", 0);
        map.put("tops", scores);

        String reply = JSON.toJSONString(map);

        // 发送排名
        for(ChoiceQuestionWebSocket user : webSocketUsers) {
            if(user.getRoomId() == _roomId) {
                try {
                    for(ObUserRaceScore score : scores) {
                        if(score.getUserid() == user.getUserId()) {
                            map.put("position", score.getTopno());
                            map.put("score", score.getScore());
                            break;
                        }
                    }
                    user.sendMessage(user._session, reply);

                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return;
    }

    /**
     * TODO 发送比赛结束通知
     * @param _roomId
     */
    public static void sendRaceGameEnd(Integer _roomId) {
        Map<String, Object> map = new HashMap<String, Object>();

        map.put("cmd", GameConst.GAME_RACE_CMD_END);
        map.put("code", 0);

        for(ChoiceQuestionWebSocket user : webSocketUsers) {

            if(user.getRoomId() == _roomId) {
                map.put("top", user.raceScore);
                map.put("score", user.raceScore);

                String reply = JSON.toJSONString(map);
                try {
                    user.sendMessage(user._session, reply);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}
